﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;
using System.Globalization;
using System.Xml.Xsl;
using iReaper.Properties;
using System.Text;
using System.IO;
using System.Net;

namespace iReaper
{
    public class OriginalContentManager
    {
        #region static

        static string Url_Of_893;
        static string Url_Of_Attributes;
        static string Path_Of_893;
        static string Path_Of_Attributes;
        static string Path_Of_Info;
        static string Update_Interval;

        
        private static OriginalContentManager _manager;
        private static System.Xml.Xsl.XslCompiledTransform xslt;
        private static XsltArgumentList args;


        public static void Init()
        {
            // Load Xslt Parser
            xslt = new System.Xml.Xsl.XslCompiledTransform(false);
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.CloseOutput = false;
            settings.Encoding = Encoding.UTF8;
            settings.Indent = false;
            settings.OmitXmlDeclaration = false;

            args = new XsltArgumentList();
            args.AddExtensionObject("http://www.ireaper.net", new XsltExtenionHelper());

            string xsltXml = Resources.infoXslt;
            xslt.Load(new XmlTextReader(new StringReader(xsltXml)), new System.Xml.Xsl.XsltSettings(true, true), null);

            // Load xml url
            Url_Of_893 = System.Configuration.ConfigurationManager.AppSettings["Url_Of_893"];
            Url_Of_Attributes = System.Configuration.ConfigurationManager.AppSettings["Url_Of_Attributes"];
            Path_Of_893 = System.Configuration.ConfigurationManager.AppSettings["Path_Of_893"];
            Path_Of_Attributes = System.Configuration.ConfigurationManager.AppSettings["Path_Of_Attributes"];
            Path_Of_Info = System.Configuration.ConfigurationManager.AppSettings["Path_Of_Info"];
            Update_Interval = System.Configuration.ConfigurationManager.AppSettings["Update_Interval"];

            // Create default manager instance
            _manager = new OriginalContentManager();
        }

        /// <summary>
        /// Get the default manager object
        /// </summary>
        public static OriginalContentManager Current
        {
            get { return _manager; }
        }

        #endregion

        #region field

        string filePathOf893;
        string filePathOfInfo;
        string filePathOfAttributes;

        XmlDocument xml893;
        DateTime lastModifiedDate;

        System.Timers.Timer timer;
        double updateInterval;

        #endregion

        public string InfoXmlPath { get { return filePathOfInfo; } }

        public event EventHandler OnXmlSynchorized;

        public OriginalContentManager()
        {
            if (!double.TryParse(Update_Interval, out updateInterval))
            {
                updateInterval = 3600 * 24 * 3;
            }
            // Get xml path
            HttpServerUtility server = HttpContext.Current.Server;
            filePathOf893 = server.MapPath(Path_Of_893);
            filePathOfAttributes = server.MapPath(Path_Of_Attributes);
            filePathOfInfo = server.MapPath(Path_Of_Info);

            // Create folder
            string folderOf893 = Path.GetDirectoryName(filePathOf893);
            if (!Directory.Exists(folderOf893))
            {
                Directory.CreateDirectory(folderOf893);
            }

            // Init logic
            lastModifiedDate = File.GetLastWriteTime(filePathOfInfo);
            TimerManager.OnTimer += new EventHandler(OnTimer);

            OnTimer(null, null);
        }

        #region Timer

        private void OnTimer(object sender, EventArgs e)
        {
            if (IfModifiedSince(Url_Of_893, lastModifiedDate))
            {
                Synchorize();
                lastModifiedDate = DateTime.Now;
            }
            else if (xml893 == null)
            {
                LoadXml();
            }
        }


        #endregion

        #region Synchorize

        public void Synchorize()
        {
            DownloadFiles();

            LoadXml();

           
        }

        private void DownloadFiles()
        {
            // Download this files
            System.Net.WebClient client = new System.Net.WebClient();
            client.DownloadFile(Url_Of_893, filePathOf893);
            DateTime lastModified;
            if (!DateTime.TryParse(client.ResponseHeaders[HttpResponseHeader.LastModified], out lastModified))
            {
                lastModified = DateTime.Now;
            }

            client.DownloadFile(Url_Of_Attributes, filePathOfAttributes);
            // Do transform
            FileStream fsInfo = new FileStream(filePathOfInfo, FileMode.Create, FileAccess.Write, FileShare.None);
            StreamReader sr = new StreamReader(filePathOf893, Encoding.UTF8, true);
            xslt.Transform(new XmlTextReader(sr),
                           args,
                           new XmlTextWriter(fsInfo, Encoding.UTF8),
                           new AttributeXmlDocumentResolver(File.ReadAllText(filePathOfAttributes, Encoding.UTF8)));
            fsInfo.Close();
            sr.Close();
            File.SetLastWriteTime(filePathOf893, lastModified);
            File.SetLastWriteTime(filePathOfAttributes, lastModified);
            File.SetLastWriteTime(filePathOfInfo, lastModified);
        }

        private void LoadXml()
        {
            XmlDocument _xml893 = new XmlDocument();
            _xml893.Load(filePathOf893);
            xml893 = _xml893;

            if (OnXmlSynchorized != null)
            {
                OnXmlSynchorized(this, EventArgs.Empty);
            }
        }

        private bool IfModifiedSince(string Url, DateTime date)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            request.IfModifiedSince = date;
            request.Method = "HEAD";
            try
            {
                request.GetResponse().Close();
                return true;
            }
            catch (WebException webEx)
            {
                if (webEx.Response != null)
                {
                    HttpWebResponse response = (HttpWebResponse)webEx.Response;
                    if (response.StatusCode == HttpStatusCode.NotModified)
                    {
                        response.Close();
                        return false;
                    }
                }
            }
            return true;
        }

        #endregion

        public XmlDocument Xml893
        {
            get { return xml893; }
        }
    }

    class XsltExtenionHelper
    {

        public string format_date(string ori)
        {
            if (ori == null)
            {
                return "";
            }

            string[] items = ori.Split('-');
            if (items.Length > 0)
            {
                string cnDate = items[0];
                DateTime date;
                if (DateTime.TryParse(cnDate, CultureInfo.GetCultureInfo("zh-CN"), DateTimeStyles.None, out date))
                {
                    return date.ToString(CultureInfo.InvariantCulture);
                }
            }

            return null;
        }
    }

    class AttributeXmlDocumentResolver : XmlResolver
    {
        XmlDocument xmldoc;
        public AttributeXmlDocumentResolver(string content)
        {
            xmldoc = new XmlDocument();
            xmldoc.LoadXml(content);
        }

        public override Uri ResolveUri(Uri baseUri, string relativeUri)
        {
            if (relativeUri == "attributes.xml")
            {
                return new Uri("file://attributes.xml");
            }
            return null;
        }

        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
        {
            return xmldoc;
        }

        public override ICredentials Credentials
        {
            set { return; }
        }
    }

    
}
